package MidTerm;

import java.util.EnumMap;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
/*
 * 单个车次的票务系统，管理余票、销售统计及票号验证
 */
class TicketSystem {
    // 使用原子计数器存储余票数量，键为座位类型，值为对应的计数器
    private final EnumMap<SeatType, AtomicInteger> seatCounters;
    //统计各类型售出票数，键为座位类型，值为对应的计数器
    private final EnumMap<SeatType, AtomicInteger> typeSales;
    //存储有效票号及其对应的座位类型，键为票号，值为对应的座位类型
    private final ConcurrentHashMap<String, SeatType> validTickets = new ConcurrentHashMap<>();
    //总销售量
    private final AtomicInteger totalSales = new AtomicInteger(0);
    private final Random random = new Random();
    //构造函数，初始化余票数量
    public TicketSystem(SeatConfig config) {
        seatCounters = new EnumMap<>(SeatType.class);
        typeSales = new EnumMap<>(SeatType.class);
        for (SeatType type : config.getSeatTypes()) {
            int quantity = config.getInitialQuantity(type);
            //创建AtomicInteger对象，并初始化余票数量
            seatCounters.put(type, new AtomicInteger(quantity));
            //创建AtomicInteger对象，并初始化类型销量为0
            typeSales.put(type, new AtomicInteger(0));
        }
    }
    /**
     * 检查是否支持指定座位类型
     * @param type 座位类型
     * @return 如果支持则返回true，否则返回false
     */
    public boolean hasSeatType(SeatType type) {
        return seatCounters.containsKey(type);
    }
    /**
     * 获取所有支持的座位类型
     * @return 座位类型数组
     */
    public SeatType[] getSeatTypes() {
        return seatCounters.keySet().toArray(new SeatType[0]);
    }
    //售票操作
    public boolean sellTicket(String trainNumber, SeatType type, int windowId) {
        AtomicInteger counter = seatCounters.get(type);//获取指定座位类型的余票计数器
        if (counter == null) return false;
        while (!Thread.currentThread().isInterrupted()) {
            int current = counter.get();
            if (current <= 0) return false;
            if (counter.compareAndSet(current, current - 1)) {
                String ticketId = String.format("%s-WIN%d-%d-%04d",
                        trainNumber, windowId, System.currentTimeMillis(), random.nextInt(10000));
                validTickets.put(ticketId, type);//添加有效票号及其对应的座位类型
                typeSales.get(type).incrementAndGet();//类型销量自增
                totalSales.incrementAndGet();

                System.out.printf("【成功】%s 售票 类型：%s 票号：%s 余票：%d 类型销量：%d \n",
                        trainNumber, type, ticketId, current - 1,
                        typeSales.get(type).get());
                return true;
            }
        }
        return false;
    }
    /**
     * 退票操作
     * @param ticketId 票号
     * @return 是否退票成功
     */
    public boolean refundTicket(String ticketId) {
        SeatType type = validTickets.get(ticketId);
        if (type == null) {
            //无效票号
            System.out.printf("【退票失败】票号：%s 原因：票号无效\n", ticketId);
            return false;
        }
        if (validTickets.remove(ticketId) != null) {
            seatCounters.get(type).incrementAndGet();//余票数量自增
            typeSales.get(type).decrementAndGet();//类型销量自减
            totalSales.decrementAndGet();//总销量自减
            System.out.printf("【退票成功】%s 票号：%s 类型：%s 新余票：%d 类型销量：%d\n",
                    ticketId.split("-")[0], ticketId, type,
                    seatCounters.get(type).get(), typeSales.get(type).get());
            return true;
        }else{
            System.out.printf("【退票失败】票号：%s 原因：票号无效或已退票\n", ticketId);
        }
        return false;
    }
    /**
     * 获取余票计数器
     * @return 余票计数器
     */
    public EnumMap<SeatType, AtomicInteger> getSeatCounters() {
        return seatCounters;
    }
    /**
     * 获取类型销量计数器
     * @return 类型销量计数器
     */
    public EnumMap<SeatType, AtomicInteger> getTypeSales() {
        return typeSales;
    }
    /**
     * 获取总销售量
     * @return 总销售量
     */
    public int getRemainingSeats(SeatType type) {
        AtomicInteger counter = seatCounters.get(type);
        return counter == null ? 0 : counter.get();
    }
}
